#include "fileCommand.h"

int getRealPath(filePath_t file_path,char *real_path) {
    strncpy(real_path,file_path.work_path,strlen(file_path.work_path));
    strncat(real_path,file_path.user_path,strlen(file_path.user_path));
    // printStack(file_path.current_path_stack);

    if(file_path.current_path_stack.current_statck_top != 0) {
        for(int i = 0;i < file_path.current_path_stack.current_statck_top;++i) {
            int size = strlen(real_path);
            if(real_path[size - 1] != '/') {
                char *concatChar = "/";
                strncat(real_path,concatChar,1);
            }
            // printf("Stack : %s\n",file_path.current_path_stack.path[i]);
            strncat(real_path,file_path.current_path_stack.path[i],strlen(file_path.current_path_stack.path[i]));
        }
    }
    // printf("real_path = %s\n",real_path);
    return 0;
}

int doCurPathStack(filePath_t *file_path,const char* path) {
    int size = strlen(path) + 1;
    char* cdPath = (char*)malloc(size*sizeof(char));
    if(cdPath == NULL) {
        // malloc 分配失败
        return -1;
    }
    memset(cdPath,0,size);
    memcpy(cdPath,path,size);
    const char* delim = "/";
    char* saveptr;
    char* token = NULL;
    if(path == NULL||strlen(path) == 0) {
        // 传入路径为空
        return -1;
    }

    // 使用"/"分割字符串
    token = strtok_r(cdPath,delim,&saveptr);
    
    while(token != NULL) {
        // printf("token = %s\n",token);
        if(strcmp(token,"..") == 0) {
            if(file_path->current_path_stack.current_statck_top > 0) {
                popFileStack(&file_path->current_path_stack);
            }else {
                // 栈为空，不可返回更上一级
                return -1;
            }
        }
        else {
            if(strcmp(token,".") != 0) {
                // 压栈
                pushFileStack(&file_path->current_path_stack,token);
            }
        }
        token = strtok_r(NULL,delim,&saveptr);
    }
    free(cdPath);
    return 0;
}


int initFilePath(filePath_t* file_path,const char* work_path,const char* user_path) {
    if(work_path == NULL || strlen(work_path) == 0) {
        getcwd(file_path->work_path,200);
    }
    else {
        // 初始化工作目录
        memcpy(file_path->work_path,work_path,strlen(work_path));
    }
    if(user_path != NULL && strlen(user_path) != 0) {
        // 初始化用户路径
        memcpy(file_path->user_path,user_path,strlen(user_path));
    }
    // 初始化用户的虚拟路径栈
    initFileStack(&file_path->current_path_stack);
    return 0;
}

int lsCommand(filePath_t file_path) {
    printf("--ls-command--\n");
    // 当前真实地址
    char real_path[1024];
    bzero(real_path,sizeof(real_path));
    getRealPath(file_path,real_path);
    DIR* current_dir = opendir(real_path);
    if(current_dir == NULL) {
        perror("opendir");
        return -1;
    }
    struct dirent *dir_message;
    while((dir_message = readdir(current_dir)) != NULL) {
        char* dname = dir_message->d_name;
        if(strcmp(dname,".") == 0 || strcmp(dname,"..") == 0) {
            continue;
        }
        printf("%5s\t",dname);
    }
    printf("\n");
    closedir(current_dir);
    return 0;
}
int cdCommand(filePath_t file_path,const char* path) {
    printf("--cd_command--\n");
    char real_path[1024];
    bzero(real_path,1024);
    doCurPathStack(&file_path,path);
    getRealPath(file_path,real_path);
    if(access(real_path,F_OK) == -1) {
        perror("目录不存在");
        return -1;
    }
    // 打印文件目录内容
    DIR* current_dir = opendir(real_path);
    if(current_dir == NULL) {
        perror("目录无法打开");
        return -1;
    }
    struct dirent * curDirent;
    while((curDirent = readdir(current_dir)) != NULL) {
        if(strcmp(curDirent->d_name,".") == 0 || strcmp(curDirent->d_name,"..") == 0) {
            continue;
        }
        // printf("%5d %10s %5s\n",curDirent->d_ino,curDirent->d_name,curDirent->d_type);
        printf("%5s\t",curDirent->d_name);
    }
    printf("\n");
    return 0;
}
int removeCommand(filePath_t file_path,const char* path) {
    printf("--remove_command--\n");
    /**
     * 1. 判断目录是否存在
     * 2. 判断目录是否为空
     * 3. 调用rmdir删除目录
     */
    doCurPathStack(&file_path,path);
    char real_path[1024] = {0};
    getRealPath(file_path,real_path);
    int ok = access(real_path,F_OK);
    if(ok == -1) {
        perror("目录无法访问");
        return -1;
    }
    // 2. 判断是否为空

    if(isEmptyDir(real_path) == 0) {
        printf("目录为空\n");
        // 3. 删除目录
        if(rmdir(real_path) == -1) {
            perror("目录删除失败");
            return -1;
        }
        // 4. 回退到上一级目录
        // cdCommand(file_path,"..");
    }
    return 0;
}
int pwdCommand(filePath_t file_path) {
    printf("--pwd_command--\n");
    char real_path[1024] = {0};
    getRealPath(file_path,real_path);
    printf("pwd = %s\n",real_path);
    return 0;
}
int mkdirCommand(filePath_t file_path,const char* path) {
    printf("--mkdir_command--\n");
    // printf("path = %s\n",path);
    doCurPathStack(&file_path,path);

    char newDirPath[1024];
    memset(newDirPath,0,1024);
    snprintf(newDirPath,sizeof(newDirPath),"%s",file_path.current_path_stack.path[file_path.current_path_stack.current_statck_top-1]);
    printStack(file_path.current_path_stack);
    printf("newDir = %s\n",newDirPath);
    // 判断是否存在父目录
    popFileStack(&file_path.current_path_stack);
    char real_path[1024];
    bzero(real_path,1024);
    getRealPath(file_path,real_path);
    int ok = access(real_path,F_OK);
    if(ok == -1) {
        perror("父目录不存在");
        return -1;
    }
    // 创建目录
    pushFileStack(&file_path.current_path_stack,newDirPath);
    getRealPath(file_path,real_path);
    if(mkdir(real_path,0666) == -1) {
        perror("目录创建失败");
        return -1;
    }

    return 0;
}

int isEmptyDir(const char* path) {
    /**
     * 1. 空返回0
     * 2. 非空返回-1
     */
    DIR* current_dir = opendir(path);
    int size = 0;
    struct dirent * curDirent;
    while((curDirent = readdir(current_dir)) != NULL) {
        if(strcmp(curDirent->d_name,".") == 0 || strcmp(curDirent->d_name,"..") == 0) {
            continue;
        }
        ++size;
        break;
    }
    closedir(current_dir);
    if(size == 0) return 0;
    return -1;
}